<?php

namespace App\Http\Services\Api\V1\App\Customer;

use App\Models\Customers\FacebookUser;
use App\Models\Setting;
use App\Services\Utils\ApiChecker;
use Laravel\Socialite\Two\FacebookProvider;

class FacebookService extends FacebookProvider
{
    use ApiChecker;

    const OAUTH_TYPE_FACEBOOK_APP = 'facebook_app';
    const OAUTH_TYPE_FACEBOOK_PC = 'facebook_pc';
    const KEY_OAUTH_FACEBOOK_APP_APP_ID = 'oauth_facebook_app_app_id';
    const KEY_OAUTH_FACEBOOK_PC_APP_ID = 'oauth_facebook_pc_app_id';
    const KEY_OAUTH_FACEBOOK_APP_APP_SECRET = 'oauth_facebook_app_app_secret';
    const KEY_OAUTH_FACEBOOK_PC_APP_SECRET = 'oauth_facebook_pc_app_secret';
    const PC_REDIRECT_URL = '%s/index.php?route=account/login/oauthCallback&type=%s';

    /**
     * FacebookService constructor.
     * @param $type
     */
    public function __construct($type)
    {
        $request = request();
        $guzzle = [];

        if ($type === self::OAUTH_TYPE_FACEBOOK_PC) {

            $this->clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_FACEBOOK_PC_APP_ID);
            $this->redirectUrl = route('pc_oauth_callback', self::OAUTH_TYPE_FACEBOOK_PC);
            $this->clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_FACEBOOK_PC_APP_SECRET);
        } else {

            $this->clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_FACEBOOK_APP_APP_ID);
            $this->redirectUrl = '';
            $this->clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_FACEBOOK_APP_APP_SECRET);
        }

        parent::__construct($request, $this->clientId, $this->clientSecret, $this->redirectUrl, $guzzle);
    }

    /**
     * app端处理facebook第三方登录，获取facebook用户的信息
     * @return mixed
     * @throws \Exception
     */
    public function handleFacebookCallback()
    {
        // laravel/socialite 请求的认证
        session(['state' => 890]);
        request()->offsetSet('state', 890);

        $user = $this->createOrUpdateUser(self::OAUTH_TYPE_FACEBOOK_APP);

        return $user;
    }

    /**
     * pc端处理Facebook第三方登录，获取配置信息
     * @return mixed
     */
    public function generateFacebookProvider()
    {
        return $this;
    }

    /**
     * pc端处理Facebook第三方登录，获取用户信息
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|null|object
     * @throws \Exception
     */
    public function facebookCallback()
    {
        $user = $this->createOrUpdateUser(self::OAUTH_TYPE_FACEBOOK_PC);

        $data = http_build_query([
            'customer_id'   => $user->customer_id ?? '',
            'token'         => $user->jwt_token ?? '',
            'type'          => self::OAUTH_TYPE_FACEBOOK_PC,
            'oauth_user_id' => $user['oauth_user_id'] ?? '',
        ]);

        return redirect(sprintf(self::PC_REDIRECT_URL, config('app.web-url'), self::OAUTH_TYPE_FACEBOOK_PC.'&'.$data));
    }

    /**
     * @param $oauth_type
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|\Laravel\Socialite\Two\User|null|object
     * @throws \Exception
     */
    public function createOrUpdateUser($oauth_type)
    {
        try {

            /** @var \Laravel\Socialite\Two\User $user */
            $user =  $this->user();
        } catch (\Exception $e){
            logger($e->getMessage());
            $this->checkIsTrue(false, trans('customer.facebook_oauth_error'));
        }

        $facebook_data = $this->assembleFacebookUser($user);
        $facebook_user = $this->updateOrCreateUser($facebook_data);

        $user = (new ThirdPartyService)->generateUser($facebook_user, $oauth_type);

        return $user;
    }

    /**
     * @see MockData::getFacebookUser();
     *
     * @param \Laravel\Socialite\Two\User $user
     * @return array
     */
    public function assembleFacebookUser(\Laravel\Socialite\Two\User $user)
    {
        $facebook_user_data = [
            'id'              => $user->id ?? '',
            'nickname'        => $user->nickname ?? '',
            'name'            => $user->name ?? '',
            'email'           => $user->email ?? '',
            'avatar'          => $user->avatar ?? '',
            'user'            => json_encode($user->user ?? ''),
            "avatar_original" => $user->avatar_original ?? '',
            "profile_url"     => $user->profileUrl ?? ''
        ];

        return $facebook_user_data;

    }

    /**
     * @param array $facebook_user_data
     * @return FacebookUser
     */
    public function updateOrCreateUser(array $facebook_user_data)
    {
        /** @var FacebookUser $facebook_user */
        $facebook_user = (new FacebookUser)->updateOrCreate (
            ['id' => $facebook_user_data['id']], $facebook_user_data
        );

        return $facebook_user;
    }
}